package com.coolgor.airvow.SQL;

import com.coolgor.airvow.File.FileIO;

import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Vector;

public class DataSourceImp implements DataSource{

  	public int checkedOut; //正在被使用数据库连接个数  
  	
  	public Vector freeConnections;   //保存空闲数据库连接的向量   
    
  	public int max;   //允许取得的最大的连接个数   
   
  	public DataBaseConfigure info;
    
    public DataSourceImp (DataBaseConfigure info) throws Exception{
    	this.info = info;
    	init();
    }
    
	private   void   init() throws Exception {
		System.out.print("|->DataSource <"+info.name+"> is initializing ...");
		freeConnections = new Vector(); 
		checkedOut=0;
		if (" ".equals(info.dbdriver)) {
			if (info.dbtype.toLowerCase().equals("access")){
				//这是JDK1.6以前的操作，目前已经废止
				//info.dbdriver="sun.jdbc.odbc.JdbcOdbcDriver";
				//JDK1.8以后，调用Ucanaccess进行连接ACCESS数据库
				info.dbdriver="net.ucanaccess.jdbc.UcanaccessDriver";
			}	
			if (info.dbtype.toLowerCase().equals("sqlserver")){
				info.dbdriver="net.sourceforge.jtds.jdbc.Driver";
			}	
			if (info.dbtype.toLowerCase().equals("mysql")){
//				info.dbdriver="org.gjt.mm.mysql.Driver";
//				info.dbdriver="com.mysql.jdbc.Driver";  //Mysql5.0+
				info.dbdriver="com.mysql.cj.jdbc.Driver";//Mysql8.0+
			}				
			if (info.dbtype.toLowerCase().equals("oracle")){
//				info.dbdriver="oracle.jdbc.driver.OracleDriver";
				info.dbdriver="oracle.jdbc.OracleDriver";
			}
			if (info.dbtype.toLowerCase().equals("sybase")){
				info.dbdriver="com.sybase.jdbc2.jdbc.SybDataSource";
			}
		}
		if (!" ".equals(info.url)) {
			if ("access".equals(info.dbtype.toLowerCase())){
				//获取当前操作系统路径的斜杠符号,若是win系统，则为“\” 若是linux系统，则为“/”
				String seperator = System.getProperty("file.separator");
				List<String> pathList = new ArrayList<String>();
				pathList.add("");
				//获取项目路径
				File f = new File("");
				String filePath = null;
				try {
					filePath = f.getCanonicalPath();
				} catch (IOException e) {
					e.printStackTrace();
				}
				filePath = filePath.replace("/", seperator) + seperator;
				pathList.add(filePath);
				pathList.add(filePath + "resources" + seperator);
				pathList.add(filePath + "configuration" + seperator);
				//获取classpath路径
				filePath = this.getClass().getResource("/").getPath().replace("/", seperator);
				pathList.add(filePath);
				pathList.add(filePath + "resources" + seperator);
				pathList.add(filePath + "configuration" + seperator);
				//循环检索文件是否存在
				File file ;
				for (int i=0;i<pathList.size();i++){
					file = new File(pathList.get(i) + info.url);
					if ((file.exists())) {
						info.url = pathList.get(i) + info.url;
						System.out.println(info.url);
						break;
					}
				}
				info.url = 	"jdbc:ucanaccess://"+info.url;
			}
		}else{
			if ("access".equals(info.dbtype.toLowerCase())){
				info.url = "database.accdb";
				//获取当前操作系统路径的斜杠符号,若是win系统，则为“\” 若是linux系统，则为“/”
				String seperator = System.getProperty("file.separator");
				List<String> pathList = new ArrayList<String>();
				pathList.add("");
				//获取项目路径
				File f = new File("");
				String filePath = null;
				try {
					filePath = f.getCanonicalPath();
				} catch (IOException e) {
					e.printStackTrace();
				}
				filePath = filePath.replace("/", seperator) + seperator;
				pathList.add(filePath);
				pathList.add(filePath + "resources" + seperator);
				pathList.add(filePath + "configuration" + seperator);
				//获取classpath路径
				filePath = this.getClass().getResource("/").getPath().replace("/", seperator);
				pathList.add(filePath);
				pathList.add(filePath + "resources" + seperator);
				pathList.add(filePath + "configuration" + seperator);
				//循环检索文件是否存在
				File file ;
				for (int i=0;i<pathList.size();i++){
					file = new File(pathList.get(i) + info.url);
					if ((file.exists())) {
						info.url = pathList.get(i) + info.url;
						System.out.println(info.url);
						break;
					}
				}
				info.url = 	"jdbc:ucanaccess://"+info.url;
			}
			if ("sqlserver".equals(info.dbtype.toLowerCase())){
				info.url="jdbc:jtds:sqlserver://";
				if (info.ip!=null) 		info.url=info.url+info.ip;
				if (info.port!=null)	info.url=info.url+":"+info.port;
				if (info.dbname!=null) 	info.url=info.url+"/"+info.dbname;
			}
			if ("oracle".equals(info.dbtype.toLowerCase())){
				info.url="jdbc:oracle:thin:@";
				if (info.ip!=null) 		info.url=info.url+info.ip;
				if (info.port!=null)	info.url=info.url+":"+info.port;
				if (info.dbname!=null) 	info.url=info.url+":"+info.dbname;
			}
			if ("mysql".equals(info.dbtype.toLowerCase())){
				info.url="jdbc:mysql://";
				if (info.ip!=null) 		info.url=info.url+info.ip;
				if (info.port!=null)	info.url=info.url+":"+info.port;
				if (info.dbname!=null) 	info.url=info.url+"/"+info.dbname;
				info.url=info.url+"?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8";
			}
			if ("sybase".equals(info.dbtype.toLowerCase())){
				info.url="jdbc:sybase:Tds:";
				if (info.ip!=null) 		info.url=info.url+info.ip;
				if (info.port!=null)	info.url=info.url+":"+info.port;
				if (info.dbname!=null) 	info.url=info.url+"/"+info.dbname;
				info.url = info.url+"?JCONNECT_VERSION=6&amp;charset=iso_1&amp;charset_converter_class=com.sybase.jdbc2.utils.Cp850Converter";
			}
		}
		if (!" ".equals(info.maxconnection)) this.max=Integer.parseInt(info.maxconnection);
		
		try  {   
			Object obj = Class.forName(info.dbdriver).newInstance();
			DriverManager.registerDriver((Driver)obj);   
		}catch(Exception   e) {   
			System.err.println("Can   not   load   driver:"+info.dbdriver);   
			System.err.println(this.getClass().getName() + ".init() - 不能正常加载驱动 "); 
//			System.out.println(this.getClass().getName() + ".init() - 不能正常加载驱动: " + e.toString()); 
			throw e;
		}  
		System.out.println("...... OK!");
	} 
	
	  /**   
	    *   取得一个空闲连接或者新建一个连接   
	 * @throws SQLException 
	    */   
	@Override
	public Connection getConnection() throws SQLException  {   
		  Connection connection = null;   
		  if(freeConnections.size()   >   0)  {   
			  connection = (Connection) freeConnections.firstElement();   
			  freeConnections.removeElementAt(0);   
			  try {   
				  if (connection.isClosed()){   
					  connection = newConnection();   
				  }   
			  }catch (SQLException sqlEx) {
//				  System.out.println(this.getClass().getName() + ".getConnection() - 创建新连接时出现异常: " + sqlEx.toString()); 
				  System.err.println(this.getClass().getName() + ".getConnection() - 创建新连接时出现异常 "); 
				  throw sqlEx;
				  //return   null;   
			  }   
		  }else {   
			  if   (checkedOut   >=   max)  {   
				  return   null;   
		  }   
			  connection   =   newConnection();   
		  }   
		  if   (connection != null)   {   
			  checkedOut++;   
		  }   
		  return   connection;   
	  }   
	    
	  /**   
	    *   建立一个新的数据库连接   
	 * @throws SQLException 
	    */   
	  private Connection newConnection() throws SQLException  {   
		  Connection connection = null;   
		  try  {   
			  if   (null == info.username)  {   
				  connection   =   DriverManager.getConnection(info.url);   
			  } else if ("".equals(info.username) || " ".equals(info.username)) {
				  connection   =   DriverManager.getConnection(info.url,"","");
			  }else{
				  connection   =   DriverManager.getConnection(info.url,info.username,info.password);   
			  }   
		  }catch   (SQLException   sqlEx) 	  {  
			  System.err.println(this.getClass().getName() + ".newConnection() - 创建新连接时出现异常 " );  
//			  System.out.println(this.getClass().getName() + ".newConnection() - 创建新连接时出现异常: " + sqlEx.toString());  
			  //e.printStackTrace();   
			  throw sqlEx;
			  //return   null;   
		  }   
		  return connection;   
	  } 
	  
	  /**   
	    *   释放连接   
	    */   
	  @Override
	public void freeConnection(Connection connection)   
	  {   
		  freeConnections.addElement(connection);   
		  checkedOut--;   
	  } 
	  
	  /**   
	    *   释放所有连接   
	 * @throws SQLException 
	    */  
	  @Override
	public void release() throws SQLException {  
		  System.out.println(" DataSource <"+info.name+"> is releasing ...");
		  Enumeration allConnections = freeConnections.elements();   
		  while (allConnections.hasMoreElements()) {   
			  Connection con = (Connection) allConnections.nextElement();   
			  try {   
				  con.close();   
			  }catch   (SQLException sqlEx) {   
//				  System.out.println(this.getClass().getName() + ".release() - 关闭连接时出现异常: " + sqlEx.toString());  
				  System.err.println(this.getClass().getName() + ".release() - 关闭连接时出现异常 " );  
				  throw sqlEx;
				  //sqlEx.printStackTrace();   
			  }   
		  }   
		  freeConnections = new Vector();   
		  checkedOut = 0;   
		  System.out.println(" DataSource <"+info.name+"> is released !");
	  }
}